/*******************************************************************************
*
*   FILE NAME:
*       Vector3.h - Vector3 class definition
*
*   DESCRIPTION:
*       Defines a vector with three components.
*
*******************************************************************************/
#pragma once

#include "Types.h"
#include "Vector2.h"

class Vector3
{
public:
    static const Vector3 Backward;
    static const Vector3 Down;
    static const Vector3 Forward;
    static const Vector3 Left;
    static const Vector3 One;
    static const Vector3 Right;
    static const Vector3 UnitX;
    static const Vector3 UnitY;
    static const Vector3 UnitZ;
    static const Vector3 Up;
    static const Vector3 Zero;

    float32 X;
    float32 Y;
    float32 Z;

    Vector3( void );
    Vector3( float32 value );
    Vector3( const Vector2& xy, float32 z );
    Vector3( float32 x, float32 y, float32 z );
    Vector3( const Vector3& other );
    ~Vector3( void );

    Vector3& operator=( const Vector3& other );
    friend boolean operator==( const Vector3& vec1, const Vector3& vec2 );
    friend boolean operator!=( const Vector3& vec1, const Vector3& vec2 );
    friend Vector3 operator+( const Vector3& vec1, const Vector3& vec2 );
    friend Vector3 operator-( const Vector3& vec1, const Vector3& vec2 );
    friend Vector3 operator*( const Vector3& vec1, const Vector3& vec2 );
    friend Vector3 operator*( const Vector3& vec1, float32 scalar );
    friend Vector3 operator*( float32 scalar, const Vector3& vec1 );
    friend Vector3 operator/( const Vector3& vec1, const Vector3& vec2 );
    friend Vector3 operator/( const Vector3& vec1, float32 divider );
    friend Vector3 operator-( const Vector3& vec );

    static Vector3 Add( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Clamp( const Vector3& vec, const Vector3& min, const Vector3& max );
    static Vector3 Cross( const Vector3& vec1, const Vector3& vec2 );
    static float32 Distance( const Vector3& vec1, const Vector3& vec2 );
    static float32 DistanceSquared( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Divide( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Divide( const Vector3& vec1, float32 divider );
    static float32 Dot( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Max( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Min( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Multiply( const Vector3& vec1, const Vector3& vec2 );
    static Vector3 Multiply( const Vector3& vec1, float32 scalar );
    static Vector3 Negate( const Vector3& vec );
    static Vector3 Normalize( const Vector3& vec );
    static Vector3 Reflect( const Vector3& vec, const Vector3& normal );
    static Vector3 Subtract( const Vector3& vec1, const Vector3& vec2 );

    static void Add( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Clamp( const Vector3& vec, const Vector3& min, const Vector3& max, Vector3& result );
    static void Cross( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Distance( const Vector3& vec1, const Vector3& vec2, float32& result );
    static void DistanceSquared( const Vector3& vec1, const Vector3& vec2, float32& result );
    static void Divide( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Divide( const Vector3& vec1, float32 divider, Vector3& result );
    static void Dot( const Vector3& vec1, const Vector3& vec2, float32& result );
    static void Max( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Min( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Multiply( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    static void Multiply( const Vector3& vec1, float32 scalar, Vector3& result );
    static void Negate( const Vector3& vec, Vector3& result );
    static void Normalize( const Vector3& vec, Vector3& result );
    static void Reflect( const Vector3& vec, const Vector3& normal, Vector3& result );
    static void Subtract( const Vector3& vec1, const Vector3& vec2, Vector3& result );
    
    float32 Length( void ) const;
    float32 LengthSquared( void ) const;

    void Normalize( void );

protected:
private:
};
